/** 
 * (#)IbatisGenericDao.java 1.0 2008-6-7 上午09:20:13 
 * 
 */
package com.hzh.blog.common.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.util.Assert;

import com.hzh.blog.common.pager.Page;
import com.hzh.blog.common.pager.PropertyFilter;

@SuppressWarnings("unchecked")
public class IbatisGenericDao extends SqlSessionDaoSupport {

	public static final String POSTFIX_INSERT = ".insert";

	public static final String POSTFIX_UPDATE = ".update";

	public static final String POSTFIX_DELETE = ".delete";

	public static final String POSTFIX_DELETE_PRIAMARYKEY = ".deleteByPrimaryKey";

	public static final String POSTFIX_SELECT = ".select";

	public static final String POSTFIX_GETALL = ".getAll";

	public static final String POSTFIX_SELECTMAP = ".selectByMap";

	public static final String POSTFIX_SELECTSQL = ".selectBySql";

	public static final String POSTFIX_COUNT = ".count";

	public static final String POSTFIX_QUERY = ".query";

	/**
	 * 根据ID获取对象
	 */
	public <T> T get(Class<T> entityClass, Serializable id) {

		T o = (T) getSqlSession().selectOne(
				getStatementId(entityClass, IbatisGenericDao.POSTFIX_SELECT),
				id);
		return o;
	}

	/**
	 * 新增对象
	 */
	public void _insert(Object o) {
		getSqlSession().insert(
				getStatementId(o.getClass(), IbatisGenericDao.POSTFIX_INSERT),
				o);
	}

	/**
	 * 保存对象
	 */
	public void _update(Object o) {
		getSqlSession().update(
				getStatementId(o.getClass(), IbatisGenericDao.POSTFIX_UPDATE),
				o);
	}

	/**
	 * 根据ID删除对象
	 */
	public <T> void removeById(Class<T> entityClass, Serializable id) {
		System.out.println("id:" + id);
		getSqlSession().delete(
				getStatementId(entityClass,
						IbatisGenericDao.POSTFIX_DELETE_PRIAMARYKEY), id);
	}
	
	/**
	 * 根据动态条件获得分页数据（使用添加后缀的count以及query statement id）
	 * @param entityClass
	 * @param propertyFilters
	 * @param page
	 * @param suffix statement id 后缀
	 * @param otherParam 其他查询参数
	 * @return
	 */
	public Page findPagerObjectListByFilter(Class entityClass, List<PropertyFilter> propertyFilters,Page page, String suffix ,Map<String, String> otherParam){
		Map paramMap = new HashMap();
		paramMap.putAll(otherParam);
		paramMap.put("propertyFilters", propertyFilters);
		// 计算总数
		Integer totalCount = (Integer) getSqlSession()
		.selectOne(
				getStatementId(entityClass,
						IbatisGenericDao.POSTFIX_COUNT+suffix),
						paramMap);
		page.setTotalItems(totalCount);
		// 如果没有数据则不继续查询
		if(totalCount>0){
			paramMap.put("page", page);
			List list = getSqlSession()
			.selectList(getStatementId(entityClass,
					IbatisGenericDao.POSTFIX_QUERY+suffix),paramMap);
			page.setResult(list);
		} else {
			page.setResult(new ArrayList());
		}
		return page;
	}
	
	/**
	 * 根据动态条件获得分页数据（使用默认的count 以及 query statement id）
	 * @param entityClass
	 * @param propertyFilters
	 * @param page
	 * @param otherParam 其他扩展参数
	 * @return
	 */
	public Page findPagerObjectListByFilter(Class entityClass, List<PropertyFilter> propertyFilters,Page page, Map<String, String> otherParam){
		return findPagerObjectListByFilter(entityClass, propertyFilters, page, "", otherParam);
	}
	/**
	 * 根据动态条件获得分页数据（使用默认的count 以及 query statement id）
	 * @param entityClass
	 * @param propertyFilters
	 * @param page
	 * @return
	 */
	public Page findPagerObjectListByFilter(Class entityClass, List<PropertyFilter> propertyFilters,Page page) {
		return findPagerObjectListByFilter(entityClass,propertyFilters,page,new HashMap<String, String>());
	}
	
	/**
	 * 分页查询函数，使用PaginatedList.
	 * 
	 * @param start
	 * @param limit
	 * @return 含17117717记录数和当前页数据的Page对象.
	 */
	public Page pagedQuery(Class entityClass, Object parameterObject, int start,
			int limit) {
		
		Page page = null;

		Assert.isTrue(start >= 0, "pageNo should start from 0");

		// 计算总数
		Integer totalCount = (Integer) getSqlSession()
				.selectOne(
						getStatementId(entityClass,
								IbatisGenericDao.POSTFIX_COUNT),
						parameterObject);

		// 如果没有数据则返回Empty Page
		Assert.notNull(totalCount, "totalCount Error");

		page = new Page();

		List list;
		int totalPageCount = 0;
		int startIndex = 0;

		// 如果pageSize小于0,则返回所有数据
		String statementId = getStatementId(entityClass,
				IbatisGenericDao.POSTFIX_QUERY);
		if (limit > 0) {

			// 计算页数
			totalPageCount = (totalCount / limit);
			totalPageCount += ((totalCount % limit) > 0) ? 1 : 0;

			// 计算skip数量
			if (totalCount > start) {
				startIndex = start;
			} else {
				startIndex = (totalPageCount - 1) * limit;
			}

			list = getSqlSession()
					.selectList(
							parameterObject==null? statementId:statementId+".if",
							parameterObject,new RowBounds(startIndex, limit));

		} else {
			list = getSqlSession()
					.selectList(
							statementId,
							parameterObject);
		}
		
		page.setResult(list);
		page.setTotalItems(totalPageCount);
		
		return page;
	}

	/**
	 * 分页查询函数，使用PaginatedList.
	 * 
	 * @param start
	 * @param limit
	 * @return 含17117717记录数和当前页数据的Page对象.
	 */
	public Page pagedQuery(Class entityClass, Map parameterObject, int start,
			int limit, String countSqlId, String pageQuerySqlId) {

		Assert.isTrue(start >= 0, "pageNo should start from 0");

		// 计算总数
		Integer totalCount = (Integer) getSqlSession()
				.selectOne(getStatementId(entityClass, countSqlId),
						parameterObject);

		// 如果没有数据则返回Empty Page
		Assert.notNull(totalCount, "totalCount Error");


		List list;
		int totalPageCount = 0;
		int startIndex = 0;

		// 如果pageSize小于0,则返回所有数捄1177,等同于getAll
		if (limit > 0) {

			// 计算页数
			totalPageCount = (totalCount / limit);
			totalPageCount += ((totalCount % limit) > 0) ? 1 : 0;

			// 计算skip数量
			if (totalCount >= start) {
				startIndex = start;
			} else {
				startIndex = (totalPageCount - 1) * limit;
			}

			if (parameterObject == null)
				parameterObject = new HashMap();

			parameterObject.put("startIndex", startIndex);
			parameterObject.put("endIndex", limit);

			list = getSqlSession().selectList(
					getStatementId(entityClass, pageQuerySqlId),
					parameterObject);

		} else {
			list = getSqlSession().selectList(
					getStatementId(entityClass, pageQuerySqlId),
					parameterObject);
		}
		return null;
	}

	/**
	 * get statement id in SQL Map file
	 * 
	 * @param entityClass
	 *            entity class
	 * @param suffix
	 *            suffix
	 * @return statement id
	 */
	private String getStatementId(Class entityClass, String suffix) {
		String className = entityClass.getSimpleName();
		return className + suffix;
	}

	public <T> List<T> queryForList(Class<T> entityClass, String statementId,
			Object parameters) {
		return getSqlSession().selectList(
				getStatementId(entityClass, statementId), parameters);
	}

	public <T> T queryForObject(Class<T> entityClass, String statementId,
			Object parameters) {
		return (T) getSqlSession().selectOne(
				getStatementId(entityClass, statementId), parameters);
	}
	
	
	public void update(Class entityClass, String statementId, Object parameters) {
		getSqlSession().update(
				getStatementId(entityClass, statementId), parameters);
	}
	
	public <T> List<T> queryAllList(Class<T> entityClass) {
		return getSqlSession().selectList(
				getStatementId(entityClass, IbatisGenericDao.POSTFIX_GETALL));
	}

}